home *** CD-ROM | disk | FTP | other *** search
- /* Test file to create a Targa height field for POVRay -- Alexander Enzmann */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #include <float.h>
-
- #ifndef M_PI
- #define M_PI 3.1415926535897932384626
- #endif
-
- static float **height_buffer, **height_buffer2;
- static int GridHeight, GridWidth;
-
- static FILE *TargaFile;
-
- void
- TargaOpen(char *filename, int x, int y)
- {
- unsigned char tgaheader[18];
- if ((TargaFile = fopen(filename, "wb")) == NULL) {
- printf("Failed to open Targa file: %s\n", filename);
- exit(1);
- }
- memset(tgaheader, 0, 18);
- tgaheader[2] = 2;
- tgaheader[12] = (unsigned char)(x & 0xFF);
- tgaheader[13] = (unsigned char)((x >> 8) & 0xFF);
- tgaheader[14] = (unsigned char)(y & 0xFF);
- tgaheader[15] = (unsigned char)((y >> 8) & 0xFF);
- tgaheader[16] = 24;
- tgaheader[17] = 0x20;
- fwrite(tgaheader, 18, 1, TargaFile);
- }
-
- void
- TargaWrite(unsigned char r, unsigned char g, unsigned char b)
- {
- fputc(b, TargaFile);
- fputc(g, TargaFile);
- fputc(r, TargaFile);
- }
-
- void
- TargaClose()
- {
- fclose(TargaFile);
- }
-
- void
- alloc_height_buffers()
- {
- int i, j;
- GridHeight = 160;
- GridWidth = 160;
-
- height_buffer = malloc(GridHeight * sizeof(float *));
- height_buffer2 = malloc(GridHeight * sizeof(float *));
- if (height_buffer == NULL || height_buffer2 == NULL) {
- printf("Failed to allocate height buffer\n");
- exit(1);
- }
- for (i=0;i<GridHeight;i++) {
- height_buffer[i] = malloc(GridWidth * sizeof(float));
- height_buffer2[i] = malloc(GridWidth * sizeof(float));
- if (height_buffer[i] == NULL || height_buffer2[i] == NULL) {
- printf("Failed to allocate element %d of height buffer\n", i);
- exit(1);
- }
- for (j=0;j<GridWidth;j++)
- height_buffer[i][j] = 0.0;
- }
- }
-
- void
- clear_temp_buffer()
- {
- int i, j;
- for (i=0;i<GridHeight;i++)
- for (j=0;j<GridWidth;j++)
- height_buffer2[i][j] = -10000.0;
- }
-
- void
- add_buffers()
- {
- int i, j;
- for (i=0;i<GridHeight;i++)
- for (j=0;j<GridWidth;j++)
- if (height_buffer2[i][j] != -10000.0)
- height_buffer[i][j] = (height_buffer[i][j]+height_buffer2[i][j])/2;
- }
-
- void
- evaluate_wake(int x0, int z0)
- {
- float wave_phase, crest_angle;
- float y;
- int x, z;
- float wave_count = 4.0;
- int wave_steps = 100;
- float phase_delta = 2.0 * M_PI / wave_steps;
- float total_phase = 2.0 * M_PI * wave_count;
- int crest_steps = 180;
- float amplitude = 64.0;
- float wave_x_scale = 3;
- float wave_z_scale = 1.4;
- int step_count = 0;
- float maxy = -1000.0;
- float miny = 1000.0;
- float decay_factor = 0.8; /* Amount of decay by wavelength */
-
- for (wave_phase=0.0;wave_phase<=total_phase;wave_phase+=phase_delta) {
- clear_temp_buffer();
- printf("Step %d of %d\r", step_count, (int)(wave_count * wave_steps));
- step_count++;
-
- /* Determine the amplitude of the wave at this phase angle */
- y = amplitude * /* Full wave height */
- cos(fmod(wave_phase, 2.0 * M_PI)) * /* Change with phase angle */
- pow(decay_factor, wave_phase); /* Decay with distance */
-
- if (y < miny) miny = y;
- if (y > maxy) maxy = y;
-
- /* Steps through the equation for wave crests, generating offsets */
- for (crest_angle=-M_PI/2.0+M_PI/((float)crest_steps);
- crest_angle<M_PI/2.0;
- crest_angle += M_PI / ((float)crest_steps)) {
- x = x0 + wave_x_scale * (float)wave_phase *
- (5 * cos(crest_angle) - cos(3 * crest_angle));
- z = z0 + wave_z_scale * (float)wave_phase *
- (sin(crest_angle) + sin(3 * crest_angle));
-
- /* Add the deflection into the buffer */
- if (x >= 0 && x < GridWidth && z >= -GridWidth/2 && z < GridHeight/2) {
- if (height_buffer2[x][z + GridWidth/2] == -10000.0)
- height_buffer2[x][z + GridWidth/2] = y;
- }
- }
- add_buffers();
- }
- printf("Max: %f, Min: %f\n", maxy, miny);
- }
-
- void
- evaluate_wake1(int x0, int z0)
- {
- int x, z;
- float xx0, xx1, y, r, t0, t1, theta, wave_phase;
- float k1, k2;
- float wave_number = 1.0;
- float amplitude = 128.0;
- float ship_velocity = 50.0;
- float wave_velocity = 50.0;
- float miny = 10000.0;
- float maxy = -10000.0;
- float decay_factor = 0.8;
- float dist_scale0 = 0.2;
- float dist_scale1 = 0.1;
-
- clear_temp_buffer();
- for (x=1;x<GridHeight;x++) {
- for (z=-GridWidth/2;z<GridWidth/2;z++) {
- xx0 = x - x0;
- xx1 = z - z0;
- theta = atan(xx1 / xx0);
- k1 = cos(theta);
- k2 = sin(theta);
- t0 = xx0 / ship_velocity;
- t1 = fabs(xx1) / wave_velocity;
- if (t1 <= t0) {
- r = sqrt(xx0 * xx0 + xx1 * xx1);
- wave_phase = (k1 * xx0 + k2 * xx1) * dist_scale0;
- /* Determine the amplitude of the wave at this phase angle */
- y = amplitude * /* Full wave height */
- cos(wave_phase) * /* Change with phase angle */
- pow(decay_factor, r * dist_scale1); /* Decay with distance */
- if (y < miny) miny = y;
- if (y > maxy) maxy = y;
- height_buffer2[x][z + GridWidth/2] = y;
- }
- }
- }
- add_buffers();
- }
-
- void
- dump_height_buffer()
- {
- unsigned char r, g, b;
- float height;
- int y, i, j;
- for (i=0;i<GridHeight;i++) {
- for (j=0;j<GridWidth;j++) {
- height = height_buffer[i][j];
- if (height < -128.0) height = -128.0;
- if (height > 127.0) height = 127.0;
- height += 128.0;
- r = height;
- height -= (float)r;
- g = 0; /* (unsigned char)(256.0 * height); */
- b = 0;
- TargaWrite(r, g, b);
- }
- }
- }
-
- void
- main()
- {
- alloc_height_buffers();
- evaluate_wake(0, 0);
- TargaOpen("wave.tga", GridWidth, GridHeight);
- dump_height_buffer();
- TargaClose();
- }
-